package com.example.demo.zaqizabatest.cglib;

import com.example.demo.zaqizabatest.common.MyTransaction;
import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;

import java.lang.reflect.Method;

/**
 * @ClassName PersonServiceInterceptor
 * @Author lys4134
 * @Date 2021/08/12 09:55:45
 * @Description PersonServiceInterceptor
 * @Version 1.0
 *
 * JDK 动态代理和 CGLIB 动态代理对比
 * JDK 动态代理只能代理实现了接口的类或者直接代理接口，而 CGLIB 可以代理未实现任何接口的类。
 * 另外， CGLIB 动态代理是通过生成一个被代理类的子类来拦截被代理类的方法调用，因此不能代理声明为 final 类型的类和方法。
 * 就二者的效率来说，大部分情况都是 JDK 动态代理更优秀，随着 JDK 版本的升级，这个优势更加明显。
 *
 *
 * 静态代理和动态代理的对比
 * 灵活性 ：动态代理更加灵活，不需要必须实现接口，可以直接代理实现类，
 * 并且可以不需要针对每个目标类都创建一个代理类。另外，静态代理中，接口一旦新增加方法，
 * 目标对象和代理对象都要进行修改，这是非常麻烦的！
 * JVM 层面 ：静态代理在编译时就将接口、实现类、代理类这些都变成了一个个实际的 class 文件。
 * 而动态代理是在运行时动态生成类字节码，并加载到 JVM 中的。
 *
 *
 **/
public class PersonServiceInterceptor implements MethodInterceptor {
    //目标类
    private Object target;
    //增强类
    private MyTransaction myTransaction;

    //构造函数注入目标类和增强类
    public PersonServiceInterceptor(Object target, MyTransaction myTransaction) {
        this.target = target;
        this.myTransaction = myTransaction;
    }

    public Object createProxy() {
        Enhancer enhancer = new Enhancer();
        enhancer.setCallback(this);
        enhancer.setSuperclass(this.target.getClass());
        enhancer.setClassLoader(this.target.getClass().getClassLoader());
        return enhancer.create();
    }

    @Override
    public Object intercept(Object arg0, Method arg1, Object[] arg2,
                            MethodProxy arg3) throws Throwable {
        myTransaction.beginTransaction();
        Object returnValue = arg1.invoke(this.target, arg2);
        myTransaction.commit();
        return returnValue;
    }

}
